import type {RequestOptions} from '@@/plugin-request/request';
import type {RequestConfig} from '@umijs/max';
import {history} from '@umijs/max';
import {message, notification} from 'antd';
import {getAuthToken} from '@/utils/auth';
import {DEFAULT_LOGIN_PATH as LOGIN_PATH} from 'kf-web-library';
import lodash from "lodash";
import React from "react";
import {AxiosResponse} from "axios";

// 接口code类型
const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，参数错误。',
  401: '用户没有权限。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};

// 与后端约定的响应数据格式
interface ResponseStructure {
  readonly timestamp: string;
  readonly bizcode: number;
  readonly code: number;
  readonly flag: boolean;
  readonly path?: string;
  readonly msg?: string;
  readonly query?: string;
  readonly status?: string;
  readonly data: any;
}

/**
 * @name 错误处理
 * pro 自带的错误处理， 可以在这里做自己的改动
 * @doc https://umijs.org/docs/max/request#配置
 */
export const errorConfig: RequestConfig = {
  errorConfig: {
    // 错误抛出
    errorThrower: (res) => {
      //看看是否是业务错误（HttpStatus为200,但是响应body中flag标识为失败的）
      const {flag, msg, bizcode, code, data} = res as unknown as ResponseStructure;
      if (!flag) {
        const error: any = new Error(msg);
        error.name = 'BizError';
        error.info = {code, bizcode, msg, data};
        throw error; // 抛出业务错误
      }
    },
    // 错误接收及处理
    errorHandler: (error: any, opts: any) => {
      if (opts?.skipErrorHandler) {
        throw error;
      }

      // errorThrower 抛出的业务错误。
      if (error.name === 'BizError') {
        const errorInfo: ResponseStructure | undefined = error.info;
        if (errorInfo) {
          const {code, bizcode, msg} = errorInfo;
          message.error(msg);
        }
      } else if (error.response) {
        // Axios 的错误
        // 请求成功发出且服务器也响应了状态码，但状态代码超出了 2xx 的范围
        const {status: httpStatusCode, statusText, data: respData} = error.response;
        const {code, bizcode, msg = error.code} = respData || {};
        switch (httpStatusCode) {
          case 401:
            message.error('未登陆或登陆已过时，请重新登陆！');
            history.push(LOGIN_PATH);
            break;
          case 400:
          case 410:
            // @ts-ignore
            const errorText = respData.msg || codeMessage[httpStatusCode as number] || statusText;
            if (respData.bizcode && respData.bizcode === 400002) {
              let errorDetailText: React.ReactNode = '';
              if (lodash.isObject(respData.data)) {
                errorDetailText = Object.entries(respData.data).map((entry, entryIndex) => {
                  return (
                    <div key={entryIndex}>
                      <span>{entry[0]}: </span><span>{entry[1] as string}</span>
                    </div>
                  );
                });
              } else {
                errorDetailText = respData.data && respData.data.toString();
              }
              notification.error({
                //message: `请求错误 ${status}: ${url}`,
                message: errorText,
                description: errorDetailText && (
                  <div>
                    <div>{errorDetailText}</div>
                  </div>
                ),
              });
            } else {
              message.error(errorText);
            }
            break;
          default:
            message.error(msg);
        }
      } else if (error.request) {
        // 请求已经成功发起，但没有收到响应
        // \`error.request\` 在浏览器中是 XMLHttpRequest 的实例，
        // 而在node.js中是 http.ClientRequest 的实例
        message.error('None response! Please retry.');
      } else {
        // 发送请求时出了点问题
        message.error('Request error, please retry.');
      }
    },
  },
  // 请求拦截器
  requestInterceptors: [
    (config: RequestOptions) => {
      //如果有认证token将其写入到Header中的Authorization中去
      const authToken = getAuthToken();
      if (authToken) {
        const headers = {...config.headers, Authorization: `Bearer ${authToken}`};
        return {...config, headers};
      }
      return config;
    },
  ],
  // 响应拦截器
  responseInterceptors: [
    (resp: AxiosResponse<any, any>) => {
      // 拦截响应数据，如果是分页数据, 给它加上序号
      if (resp.data?.flag) {
        if (resp.data?.page && resp.data?.pageSize && Array.isArray(resp.data?.data)) {
          resp.data.data.forEach((t: any, tIndex: number) => {
            t["_seq_"] = ((resp.data?.page || 1) - 1) * (resp.data?.pageSize || 0) + (tIndex + 1)
          });
        }
      }
      return resp;
    },
  ],
};
